﻿
Imports std

Partial Public Class distributor
    Protected Function redundance_aggregate(ByVal targetJobs() As indexedJob,
                                            ByVal inputJob As ijob,
                                            ByVal redundance_count As UInt32,
                                            ByVal single_aggregate As _do(Of indexedJob, UInt32, Boolean)) As Boolean
        aggregate_internal.assert_input(targetJobs, inputJob)
        assert(Not single_aggregate Is Nothing)
        assert(targetJobs.Length() = redundance_count)
        Return foreach_redundance_queue(inputJob,
                                        Function(ByRef i As UInt32, ByRef hash As UInt32) As Boolean
                                            assert(i < targetJobs.Length())
                                            Return single_aggregate(unref(targetJobs(i)), hash)
                                        End Function)
    End Function

    Protected Function redundance_aggregate(ByVal targetJobs() As indexedJob,
                                            ByVal inputJob As ijob,
                                            ByVal single_aggregate As _do(Of indexedJob, UInt32, Boolean)) As Boolean
        assert(Not redundance_count Is Nothing)
        Return redundance_aggregate(targetJobs, inputJob, redundance_count(), single_aggregate)
    End Function

    Protected Delegate Function compare_delegate(ByVal this As ijob, ByVal that As ijob) As Int32
    Protected Function redundance_compare_aggregate(ByVal targetJobs() As indexedJob,
                                                    ByVal inputJob As ijob,
                                                    ByVal compare As compare_delegate,
                                                    Optional ByRef succ_indexes As [set](Of UInt32) = Nothing,
                                                    Optional ByRef failed_indexes As [set](Of UInt32) = Nothing) _
                                                   As Boolean
        assert(Not compare Is Nothing)
        assert(Not redundance_count Is Nothing)
        [set](Of UInt32).initial_instance(succ_indexes)
        [set](Of UInt32).initial_instance(failed_indexes)
        Dim si As [set](Of UInt32) = Nothing
        Dim fi As [set](Of UInt32) = Nothing
        si = succ_indexes
        fi = failed_indexes
        If redundance_aggregate(targetJobs, inputJob, redundance_count(),
                                Function(ByRef tj As indexedJob, ByRef queueIndex As UInt32) As Boolean
                                    If tj.finished() Then
                                        Dim cmp As Int32 = 0
                                        cmp = compare(tj.job(), inputJob)
                                        If cmp > 0 Then
                                            assert(inputJob.copy(tj))
                                            assert(fi.insert(si))
                                            si.clear()
                                            si.insert(queueIndex)
                                        ElseIf cmp = 0 Then
                                            si.insert(queueIndex)
                                        Else
                                            fi.insert(queueIndex)
                                        End If
                                    Else
                                        fi.insert(queueIndex)
                                    End If
                                    Return True
                                End Function) Then
            If succ_indexes.size() = 0 Then
                assert(inputJob.copy(targetJobs(0)))
            End If
            assert(succ_indexes.size() + failed_indexes.size() = redundance_count())
            Return True
        Else
            Return False
        End If
    End Function
End Class
